package com.ctshk.rpc.order.season.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.dto.payment.CallPayDTO;
import com.ctshk.common.enums.Currency;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.AppReq;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.req.pay.NotifyConsumeReq;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SeasonOrderManager;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.bus.dto.BusProductDTO;
import com.ctshk.rpc.bus.service.IBusProductService;
import com.ctshk.rpc.finance.json.AccountJson;
import com.ctshk.rpc.finance.req.bill.BillAddCollectionReq;
import com.ctshk.rpc.finance.req.bill.BillAddRefundReq;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.iotc.dto.OperateBankPreferenceQueryDTO;
import com.ctshk.rpc.iotc.dto.OperatePromotionQueryDTO;
import com.ctshk.rpc.iotc.req.OperateBankConformQueryReq;
import com.ctshk.rpc.iotc.req.OperateBankDeductReq;
import com.ctshk.rpc.iotc.req.OperatePromotionQueryReq;
import com.ctshk.rpc.iotc.service.IOperateBankPreferenceService;
import com.ctshk.rpc.iotc.service.IOperatePromotionService;
//import com.ctshk.rpc.localfun.dto.CustomDto;
import com.ctshk.rpc.localfun.dto.LocalFunProductDetailByIdDTO;
import com.ctshk.rpc.localfun.req.LocalFunProductDetailReq;
import com.ctshk.rpc.localfun.req.LocalFunStockReq;
import com.ctshk.rpc.localfun.service.ILocalFunProductSaleRecordService;
import com.ctshk.rpc.localfun.service.ILocalFunProductService;
import com.ctshk.rpc.order.scenic.req.Scenic0rderCancelReq;
import com.ctshk.rpc.order.scenic.req.Scenic0rderRefundDetailReq;
import com.ctshk.rpc.order.scenic.service.IScenicOrderService;
import com.ctshk.rpc.order.season.dto.*;
import com.ctshk.rpc.order.season.entity.*;
import com.ctshk.rpc.order.season.mapper.*;
import com.ctshk.rpc.order.season.req.*;
import com.ctshk.rpc.order.season.service.*;
import com.ctshk.rpc.order.train.req.TrainCancelOrderReq;
import com.ctshk.rpc.order.train.service.ITrainOrderService;
import com.ctshk.rpc.payment.enums.PayCurrency;
import com.ctshk.rpc.payment.enums.PaymentMethod;
import com.ctshk.rpc.payment.req.PayCommonReq;
import com.ctshk.rpc.payment.service.IPayService;

import com.ctshk.rpc.scenic.dto.ScenicProductListDTO;
import com.ctshk.rpc.scenic.service.IScenicProductService;
import com.ctshk.rpc.season.dto.FixedSeasonDetailsDTO;
import com.ctshk.rpc.season.dto.PackageProductCostDTO;
import com.ctshk.rpc.season.req.PassengerReq;
import com.ctshk.rpc.season.service.*;
import com.ctshk.rpc.stamp.req.LevyRequest;
import com.ctshk.rpc.stamp.service.ILevyService;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.req.DispatchOrderRuleGetUserReq;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.service.*;
import com.ctshk.rpc.user.service.IOrderEsService;
import com.ctshk.rpc.user.service.IUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import com.github.houbb.heaven.util.util.CollectionUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


/**
 * <p>
 * 套票订单 服务实现类
 * </p>
 *
 * @author 杨林
 * @since 2021-03-24
 */
@Slf4j
@DubboService
public class SeasonOrderServiceImpl extends ServiceImpl<SeasonOrderMapper, SeasonOrder> implements ISeasonOrderService {

    @Autowired
    private SeasonOrderTouristMapper touristMapper;
    @Autowired
    private SeasonOrderInsuranceMapper insuranceMapper;
    @Autowired
    private SeasonOrderMapper seasonOrderMapper;
    @Autowired
    private SeasonOrderRefundMapper seasonOrderRefundMapper;
    @Autowired
    SeasonProductOrderTouristTypeMapper seasonProductOrderTouristTypeMapper;
    @Autowired
    private ISeasonProductOrderTouristTypeService orderTouristTypeService;
    @Autowired
    private ISeasonProductOrderAirService orderAirService;
    @Autowired
    private ISeasonProductOrderBusService orderBusService;
    @Autowired
    private ISeasonProductOrderHotelService orderHotelService;
    @Autowired
    private ISeasonProductOrderTrainService orderTrainService;
    @Autowired
    private ISeasonProductOrderScenicService orderScenicService;
    @Autowired
    private ISeasonProductOrderLocalFunService orderLocalFunService;
    @Autowired
    private ISeasonProductOrderShipService orderShipService;
    @Autowired
    private SeasonOrderCollectionMapper seasonOrderCollectionMapper;
    @Autowired
    private ISeasonOrderReceiptService seasonOrderReceiptService;
    @Autowired
    private ISeasonOrderInsuranceService insuranceService;
    @Autowired
    private ISeasonOrderCollectionService collectionService;
    @Autowired
    private ISeasonOrderTouristService seasonOrderTouristService;
    @Autowired
    private SeasonProductOrderScenicMapper orderScenicMapper;
    @Autowired
    private SeasonProductOrderTrainMapper orderTrainMapper;

    @Autowired
    private ISeasonProductOrderCommodityService orderCommodityService;
    @Autowired
    private SeasonOrderInsuranceMapper seasonOrderInsuranceMapper;


    @DubboReference
    private ISeasonFixedProductService productService;
    @DubboReference
    private ISysDepartmentService iSysDepartmentService;
    @DubboReference
    private ISysUserService iSysUserService;
    @DubboReference
    private IUserService iUserService;
    @DubboReference
    private ISeasonDynamicProductPackageService dynamicProductPackageService;
    //汇率服务
    @DubboReference
    private IMainDataCurrencyService mainDataCurrencyService;
    @DubboReference
    private IOperateBankPreferenceService operateBankPreferenceService;
    //审批服务类
    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private ISeasonFixedProductPackageService seasonFixedProductPackageService;
    //财务收款及退款服务类
    @DubboReference
    private IFinanceBillService financeBillService;
    @DubboReference
    private ILocalFunProductSaleRecordService localFunProductSaleRecordService;
    @DubboReference
    private IScenicOrderService scenicOrderService;
    @DubboReference
    private IOperatePromotionService iOperatePromotionService;
    @DubboReference
    private ITrainOrderService trainOrderService;
    @DubboReference
    private IDispatchOrderRuleService dispatchOrderRuleService;


    @DubboReference
    private ISeasonFixedProductPackageTrainService seasonFixedProductPackageTrainService;
    @DubboReference
    private ISeasonFixedProductPackageBusService seasonFixedProductPackageBusService;
    @DubboReference
    private ISeasonFixedProductPackageAirService seasonFixedProductPackageAirService;
    @DubboReference
    private ISeasonFixedProductPackageShipService seasonFixedProductPackageShipService;
    @DubboReference
    private ISeasonFixedProductPackageScenicService seasonFixedProductPackageScenicService;
    @DubboReference
    private ISeasonFixedProductPackageHotelService seasonFixedProductPackageHotelService;
    @DubboReference
    private ISeasonFixedProductPackageLocalFunService seasonFixedProductPackageLocalFunService;
    @DubboReference
    private ISeasonFixedProductPackageCommodityService seasonFixedProductPackageCommodityService;
    @DubboReference
    private ILevyService levyService;
    @DubboReference
    private ILocalFunProductService iLocalFunProductService;

    @DubboReference
    IPayService payService;

    @DubboReference
    private IOrderEsService orderEsService;
    @DubboReference
    private IScenicProductService iScenicProductService;
    @DubboReference
    private IBusProductService iBusProductService;
    @DubboReference
    private ISeasonFixedProductService iSeasonFixedProductService;

    /* @MethodName:
       填写订单信息 保存数据
     * @Description: TODO
     * @Param:
     * @Return: 
     * @Author: 杨林
     * @Date:2021/3/24 11:53
    **/

    @Override
    public Result callPay(SeasonPortExpressOrderAppCallPayReq callPayReq) {
        log.info("【套票订单APP-唤起支付】方法入参:{}", JSON.toJSONString(callPayReq));
        Result pay = null;
        try {
            SeasonOrder order = getById(callPayReq.getId());
            if (Objects.isNull(order)) {
                return Result.failed(SystemError.SEASON_TICKET_20017);
            }
            PayCommonReq payCommonReq = new PayCommonReq();
//            payCommonReq.setOrderNumber(order.getOrderNumber());
            payCommonReq.setOrderValidTime(order.getPayExpireDate());
            payCommonReq.setCurrency(PayCurrency.HKD);
            payCommonReq.setTotalFee(order.getReceivableAmount());
            payCommonReq.setPaymentMethod(PaymentMethod.getByCode(callPayReq.getPaymentMethodCode()));
            payCommonReq.setNotifyUrl(SeasonOrderManager.CUSTOM_URI);
            payCommonReq.setSubject("支付");
            payCommonReq.setBody("支付");
            log.info("【套票订单APP-唤起支付】支付入参:{},userId:{}", JSON.toJSONString(payCommonReq), order.getSalesmanId());
            pay = payService.pay(payCommonReq, order.getSalesmanId());
            log.info("【套票订单APP-唤起支付】支付回参:{}", JSON.toJSONString(pay));
        } catch (BusinessException e) {
            log.error("【套票订单APP-唤起支付】唤起支付失败失败,error:{}", e.getMessage(), e);
            throw new BusinessException(SystemError.getDefined(e.getCode()));
        } catch (Exception e) {
            log.error("【套票订单APP-唤起支付】系统异常,error:{}", e.getMessage(), e);
            throw new BusinessException(SystemError.SYS_500);
        }
        return pay;
    }

    @Override
    public Result payment(NotifyConsumeReq notifyConsumeReq) {
        PaymentMethod paymentMethod = PaymentMethod.getByCode(notifyConsumeReq.getPaymentMethod());
        SeasonOrderPayReq seasonOrderPayReq = new SeasonOrderPayReq();
        seasonOrderPayReq.setOrderId(Long.valueOf(notifyConsumeReq.getOrderNumber()));
        seasonOrderPayReq.setCurrencyId(Currency.HKD.getCode());
        seasonOrderPayReq.setCurrency(Currency.HKD.getCurrency());
        seasonOrderPayReq.setCollectionWayId(paymentMethod.getPayRefundMethodId()); //付款方式
        seasonOrderPayReq.setCollectionWay(paymentMethod.getName());   //付款方式
        seasonOrderPayReq.setPayer(notifyConsumeReq.getPaymentAccount()); //付款账号
        seasonOrderPayReq.setCollectionAmount(notifyConsumeReq.getAmount());
        List<SeasonOrderPayReq> reqList = new ArrayList<>();
        reqList.add(seasonOrderPayReq);

        SeasonOrder seasonOrder = seasonOrderMapper.selectById(Long.valueOf(notifyConsumeReq.getOrderNumber()));

        return saveOrderPay(reqList, seasonOrder.getChargeUserId());
    }

    @Override
    public CallPayDTO getCallPayInfo(Long id) {

        SeasonOrder seasonOrder = seasonOrderMapper.selectById(id);

        if(seasonOrder == null){
            return null;
        }

        CallPayDTO callPayDTO = new CallPayDTO();
        callPayDTO.setOrderNumber(String.valueOf(seasonOrder.getId()));
        callPayDTO.setTotalFee(seasonOrder.getSeasonAmount());
        callPayDTO.setOrderValidTime(seasonOrder.getPayExpireDate());
        callPayDTO.setCurrency(com.ctshk.common.enums.payment.PayCurrency.HKD);
        callPayDTO.setSubject(seasonOrder.getProductName());
        callPayDTO.setSalesmanId(seasonOrder.getSalesmanId());
        callPayDTO.setBody("固定套票产品");

        return callPayDTO;
    }

    @Override
    public Result saveSeasonOrderTob(SeasonOrderReq req, Long userId, Integer channelType) {
        Long seasonOrderId = req.getOrderId();
        SeasonOrder seasonOrder = null;
        boolean flag = false;
        if (seasonOrderId != null && seasonOrderId != 0L) {
            seasonOrder = getById(seasonOrderId);
            flag = true;
        }
        Integer productType = req.getProductType();
        if (userId == null || userId == 0L) {
            DispatchOrderRuleGetUserReq dispatchOrderRuleGetUserReq = new DispatchOrderRuleGetUserReq();
            dispatchOrderRuleGetUserReq.setBusinessTypeId(SeasonType.PRODUCT_FIXED_TYPE.getCode() == productType ? SystemBusinessType.FIXED_PACKAGE_TICKET.getCode() : SystemBusinessType.DYNAMIC_PACKAGE_TICKET.getCode());
            dispatchOrderRuleGetUserReq.setCompanyType(CompanyType.HK_CT.getCode());
            try {
                Result<Long> userIdResult = dispatchOrderRuleService.getDispatchUserId(dispatchOrderRuleGetUserReq);
                if (userIdResult.isSuccess()) {
                    userId = userIdResult.getData();
                }
            } catch (Exception e) {
                log.error("调用系统服务获取销售人id发生异常", e);
            }
        }
        Long productId = req.getProductId();//固定套票Id
        //主体信息
        FixedSeasonDetailsDTO fixedSeason = null;
        LocalDateTime now = LocalDateTime.now();
        if (!flag) {
            if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == productType) {//固定套票
                fixedSeason = productService.getFixedProductBaseDTO(productId);
                if (Objects.isNull(fixedSeason)) {
                    return Result.failed(SystemError.SEASON_TICKET_20004);
                }
                req.setTravelNights(fixedSeason.getTravelNights());
            }
            seasonOrder = EntityUtil.copy(fixedSeason, SeasonOrder.class);
            seasonOrder.setDepartDate(fixedSeason.getStartDate());
            //动态套票
            if (SeasonType.PRODUCT_DYNAMIC_TYPE.getCode() == productType) {
                //保存动态套票 主要是生成id 保存动态套票名字
                //票的选择的产品 1:机票 2:酒店 3:巴士 4:船票 5:火车票 6:景点门票 7:当地玩乐
                String productFlag = req.getSeasonPackageProductFlag();
                Long packageId = dynamicProductPackageService.saveDynamicProductInfo(productFlag, userId);
            }
            seasonOrder.setProductType(req.getProductType());
            seasonOrderId = SnowflakeIdWorker.nextId();
            seasonOrder.setId(seasonOrderId);
            seasonOrder.setCreateId(userId);
            //负责人id
            seasonOrder.setGmtCreate(now);
            seasonOrder.setIsDeleted(IsDeletedCode.NO.getCode());
            //销售方式 1.单读 2.打包
            seasonOrder.setSalesMethods(2);
            try {
                UserDTO userDTO = iSysUserService.queryCacheUser(userId);
                seasonOrder.setOrderNumber(SeasonOrderManager.getSellOrderNumer(userDTO.getDeptCode(), userDTO.getEmployeeNumber()));//销售单号
                seasonOrder.setSalesmanId(userDTO.getId()); //销售id
                seasonOrder.setSalesmanName(userDTO.getUsername());//销售名字
            } catch (Exception e) {
                log.error("调用系统服务获取销售人员发生异常", e);
            }
            seasonOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());//付款状态
            seasonOrder.setCancelStatus(NumberConstant.ZERO.getValue());//取消状态
            seasonOrder.setSource(OrderSource.CPM.getCode());
            seasonOrder.setSeasonPackageProductFlag(fixedSeason.getPackageProductFlag());//销售名字
            req.setSeasonPackageProductFlag(fixedSeason.getPackageProductFlag());
            /**最晚付款时间为创建订单后30分钟*/
            seasonOrder.setPayExpireDate(now.plusMinutes(30));

        }

        Long relId = req.getChannelId();
        if (SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode() == channelType) {
            if (SeasonType.PRODUCT_DYNAMIC_TYPE.getCode() == productType) {
                relId = userId;
            } else {
                relId = req.getChargeUserId();
            }
        }


        BigDecimal seasonAmount = getPackageProduct(req, channelType, relId);//套票金额
        if (seasonAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return Result.failed(SystemError.SEASON_TICKET_20016);
        }
        //来源
        //旅客信息
        List<SeasonOrderTouristDataReq> touristDataDTOList = req.getSeasonOrderTouristDataList();
        /**旅客唯一标识对应的 旅客IdMap*/
        Map<String, Long> touristMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(touristDataDTOList)) {
            Long finalUserId = userId;
            Long finalSeasonOrderId = seasonOrderId;
            List<SeasonOrderTourist> tourList = touristDataDTOList.stream().map(
                    tourReq -> {
                        SeasonOrderTourist tour = EntityUtil.copy(tourReq, SeasonOrderTourist.class);
                        Long id = SnowflakeIdWorker.nextId();
                        tour.setId(id);
                        tour.setCreateId(finalUserId);
                        tour.setGmtCreate(now);
                        tour.setIsDeleted(IsDeletedCode.NO.getCode());
                        tour.setOrderId(finalSeasonOrderId);
                        touristMap.put(tourReq.getTouristFlag(), id);
                        return tour;
                    }
            ).collect(Collectors.toList());
            touristMapper.insertBatchSomeColumn(tourList);
        }


        BigDecimal insuranceAmount = BigDecimal.ZERO;//保险总额
        //保险信息
        if (req.getBuyInsurance() == NumberConstant.ONE.getValue()) {
            List<SeasonOrderInsuranceDTO> insuranceDTOList = req.getSeasonOrderInsuranceDataList();
            if (CollectionUtil.isEmpty(insuranceDTOList)) {
                return Result.failed(SystemError.SEASON_TICKET_20013);
            }
            List<SeasonOrderInsurance> insurancesList = new LinkedList<>();
            for (SeasonOrderInsuranceDTO insuranceDto : insuranceDTOList) {
                SeasonOrderInsurance insurance = EntityUtil.copy(insuranceDto, SeasonOrderInsurance.class);
                insurance.setId(SnowflakeIdWorker.nextId());
                insurance.setOrderId(seasonOrderId);
                insurance.setIsDeleted(IsDeletedCode.NO.getCode());
                insurance.setCreateId(userId);
                insurance.setGmtCreate(now);
                insuranceAmount.add(insuranceDto.getInsurancePrice());
                //旅客类型标识
                List<String> insuredPersons = insuranceDto.getInsuredPersons();
                List<String> idList = new LinkedList<>();
                for (String insuredPerson : insuredPersons) {
                    Long touristId = touristMap.get(insuredPerson);
                    if (touristId == null) {
                        return Result.failed(SystemError.SEASON_TICKET_20014);
                    }
                    idList.add(String.valueOf(touristId));
                }
                insurance.setInsuredPerson(idList.stream().collect(Collectors.joining(",")));
                insurancesList.add(insurance);
            }
            insuranceMapper.insertBatchSomeColumn(insurancesList);
        }


        log.info("套票下单金额为："+seasonAmount);
        seasonOrder.setSeasonAmount(seasonAmount);//套票金额
        seasonOrder.setInsuranceAmount(insuranceAmount);
        BigDecimal orderAmount = insuranceAmount.add(seasonAmount);
        seasonOrder.setOrderAmount(orderAmount);
        seasonOrder.setReceivableAmount(orderAmount);//应收 就等于全部的
        if (flag) {
            seasonOrderMapper.updateById(seasonOrder);
        } else {
            seasonOrder.setUserId(userId);
            seasonOrderMapper.insert(seasonOrder);
            //保存订单 打包各个产品的信息
            saveSeasonPackageOrder(req, userId, seasonOrderId);
            sendOrderToAppUser(seasonOrder.getId());
        }
        return Result.success(seasonOrderId);
    }

    private Long getSaleManId(String companyType) {
        DispatchOrderRuleGetUserReq dispatchOrderRuleGetUserReq = new DispatchOrderRuleGetUserReq();
        dispatchOrderRuleGetUserReq.setBusinessTypeId(SystemBusinessType.FIXED_PACKAGE_TICKET.getCode());
        dispatchOrderRuleGetUserReq.setCompanyType(companyType);
        Result<Long> result = dispatchOrderRuleService.getDispatchUserId(dispatchOrderRuleGetUserReq);
        if (!result.isSuccess()) {
            log.error("【固定套票APP-提交订单】获取销售人失败:{},msg:{}", result.getCode(), result.getMsg());
            throw new BusinessException(SystemError.getDefined(result.getCode()));
        }
        return result.getData();
    }

    //@GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public Result saveSeasonOrder(SeasonOrderReq req, Long userId, Integer channelType, AppReq appReq) {
        Long seasonOrderId = req.getOrderId();
        SeasonOrder seasonOrder = null;
        boolean flag = false;
        Long productId = req.getProductId();//固定套票Id
        if (seasonOrderId != null && seasonOrderId != 0L) {
            seasonOrder = getById(seasonOrderId);
            productId = seasonOrder.getProductId();
            req.setProductType(seasonOrder.getProductType());

            flag = true;
        }
        Integer productType = req.getProductType();
//        DispatchOrderRuleGetUserReq dispatchOrderRuleGetUserReq = new DispatchOrderRuleGetUserReq();
//        dispatchOrderRuleGetUserReq.setBusinessTypeId(SeasonType.PRODUCT_FIXED_TYPE.getCode() == productType ? SystemBusinessType.FIXED_PACKAGE_TICKET.getCode() : SystemBusinessType.DYNAMIC_PACKAGE_TICKET.getCode());
//        dispatchOrderRuleGetUserReq.setCompanyType(CompanyType.HK_CT.getCode());
//        try {
//            Result<Long> userIdResult = dispatchOrderRuleService.getDispatchUserId(dispatchOrderRuleGetUserReq);
//            if (userIdResult.isSuccess()) {
//                userId = userIdResult.getData();
//            }
//        } catch (Exception e) {
//            log.error("调用系统服务获取销售人id发生异常", e);
//        }

        //主体信息
        FixedSeasonDetailsDTO fixedSeason = null;
        LocalDateTime now = LocalDateTime.now();

        if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == productType) {//固定套票
            fixedSeason = productService.getFixedProductBaseDTO(productId);
            if (Objects.isNull(fixedSeason)) {
                return Result.failed(SystemError.SEASON_TICKET_20004);
            }
            req.setTravelNights(fixedSeason.getTravelNights());
            req.setChargeUserId(fixedSeason.getChargeUserId());
        }

        if (!flag) {
            seasonOrder = EntityUtil.copy(fixedSeason, SeasonOrder.class);
            seasonOrder.setDepartDate(req.getStartDate());
            //动态套票
            if (SeasonType.PRODUCT_DYNAMIC_TYPE.getCode() == productType) {
                //保存动态套票 主要是生成id 保存动态套票名字
                //票的选择的产品 1:机票 2:酒店 3:巴士 4:船票 5:火车票 6:景点门票 7:当地玩乐
                String productFlag = req.getSeasonPackageProductFlag();
                Long packageId = dynamicProductPackageService.saveDynamicProductInfo(productFlag, userId);
            }
            seasonOrder.setProductType(req.getProductType());
            seasonOrderId = SnowflakeIdWorker.nextId();
            seasonOrder.setId(seasonOrderId);
            seasonOrder.setCreateId(userId);
            //负责人id
            seasonOrder.setGmtCreate(now);
            seasonOrder.setIsDeleted(IsDeletedCode.NO.getCode());
            //销售方式 1.单读 2.打包
            seasonOrder.setSalesMethods(2);
            try {
                Long saleManId = getSaleManId(appReq.getCompanyType());
                UserDTO userDTO = iSysUserService.queryCacheUser(saleManId);
                seasonOrder.setOrderNumber(SeasonOrderManager.getSellOrderNumer(userDTO.getDeptCode(), userDTO.getEmployeeNumber()));//销售单号
                seasonOrder.setSalesmanId(userDTO.getId()); //销售id
                seasonOrder.setCreateId(userDTO.getId());
                seasonOrder.setSalesmanName(userDTO.getUsername());//销售名字
            } catch (Exception e) {
                log.error("调用系统服务获取销售人员发生异常", e);
            }
            seasonOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());//付款状态
            seasonOrder.setCancelStatus(NumberConstant.ZERO.getValue());//取消状态
            seasonOrder.setSource(OrderSource.CPM.getCode());
            seasonOrder.setSeasonPackageProductFlag(fixedSeason.getPackageProductFlag());//销售名字

        }

        req.setSeasonPackageProductFlag(fixedSeason.getPackageProductFlag());

//        Long relId = req.getChannelId();
//        if (SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode() == channelType) {
//            if (SeasonType.PRODUCT_DYNAMIC_TYPE.getCode() == productType) {
//                relId = userId;
//            } else {
//                relId = req.getChargeUserId();
//            }
//        }


        BigDecimal seasonAmount = null;


        if(!flag){

            seasonAmount = getPackageProduct(req, SeasonType.ONLINE_SELF_CHANNEL_TYPE.getCode(),appReq.getChannelId());//套票金额
            log.info("套票金额："+seasonAmount);
            if (seasonAmount.compareTo(BigDecimal.ZERO) <= 0) {
                return Result.failed(SystemError.SEASON_TICKET_20016);
            }
        }else{
            seasonAmount = seasonOrder.getOrderAmount();
        }


        //来源
        //旅客信息
        List<SeasonOrderTouristDataReq> touristDataDTOList = req.getSeasonOrderTouristDataList();
        /**旅客唯一标识对应的 旅客IdMap*/
        Map<String, Long> touristMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(touristDataDTOList)) {
            Long finalUserId = userId;
            Long finalSeasonOrderId = seasonOrderId;
            List<SeasonOrderTourist> tourList = touristDataDTOList.stream().map(
                    tourReq -> {
                        SeasonOrderTourist tour = EntityUtil.copy(tourReq, SeasonOrderTourist.class);
                        Long id = SnowflakeIdWorker.nextId();
                        tour.setId(id);
                        tour.setCreateId(finalUserId);
                        tour.setGmtCreate(now);
                        tour.setIsDeleted(IsDeletedCode.NO.getCode());
                        tour.setOrderId(finalSeasonOrderId);
                        touristMap.put(tourReq.getTouristFlag(), id);
                        return tour;
                    }
            ).collect(Collectors.toList());
            touristMapper.insertBatchSomeColumn(tourList);
        }


        BigDecimal insuranceAmount = BigDecimal.ZERO;//保险总额
        //保险信息
        if (req.getBuyInsurance() == NumberConstant.ONE.getValue()) {
            List<SeasonOrderInsuranceDTO> insuranceDTOList = req.getSeasonOrderInsuranceDataList();
            if (CollectionUtil.isEmpty(insuranceDTOList)) {
                return Result.failed(SystemError.SEASON_TICKET_20013);
            }
            List<SeasonOrderInsurance> insurancesList = new LinkedList<>();
            for (SeasonOrderInsuranceDTO insuranceDto : insuranceDTOList) {
                SeasonOrderInsurance insurance = EntityUtil.copy(insuranceDto, SeasonOrderInsurance.class);
                insurance.setId(SnowflakeIdWorker.nextId());
                insurance.setOrderId(seasonOrderId);
                insurance.setIsDeleted(IsDeletedCode.NO.getCode());
                insurance.setCreateId(userId);
                insurance.setGmtCreate(now);
                insuranceAmount.add(insuranceDto.getInsurancePrice());
                //旅客类型标识
                List<String> insuredPersons = insuranceDto.getInsuredPersons();
                List<String> idList = new LinkedList<>();
                for (String insuredPerson : insuredPersons) {
                    Long touristId = touristMap.get(insuredPerson);
                    if (touristId == null) {
                        return Result.failed(SystemError.SEASON_TICKET_20014);
                    }
                    idList.add(String.valueOf(touristId));
                }
                insurance.setInsuredPerson(idList.stream().collect(Collectors.joining(",")));
                insurancesList.add(insurance);
            }
            insuranceMapper.insertBatchSomeColumn(insurancesList);
        }


        if (flag) {
            seasonOrder.setPayExpireDate(LocalDateTime.now().plusMinutes(30));
            //修改设置订单联系人信息
            seasonOrder.setContactName(req.getContactName());
            seasonOrder.setContactMobile(req.getContactMobile());
            seasonOrder.setContactMobileAreaCodeId(req.getContactMobileAreaCodeId());
            seasonOrder.setContactMobileAreaCode(req.getContactMobileAreaCode());
            seasonOrder.setContactEmail(req.getContactEmail());
            seasonOrder.setAppellation(req.getAppellation());
            seasonOrderMapper.updateById(seasonOrder);
        } else {
            log.info("套票下单金额为："+seasonAmount);
            seasonOrder.setSeasonAmount(seasonAmount);//套票金额
            seasonOrder.setInsuranceAmount(insuranceAmount);
            BigDecimal orderAmount = insuranceAmount.add(seasonAmount);
            seasonOrder.setOrderAmount(orderAmount);
            seasonOrder.setReceivableAmount(orderAmount);//应收 就等于全部的
            seasonOrder.setUserId(userId);
            seasonOrderMapper.insert(seasonOrder);
            //保存订单 打包各个产品的信息
            saveSeasonPackageOrder(req, userId, seasonOrderId);
            Long id = seasonOrder.getId();
            if(null!=id){
                List<SeasonProductOrderTouristType> list = new ArrayList<>(2);
                 Integer adult = req.getAdult();
                if(adult!=null){
                    SeasonProductOrderTouristType orderTouristType = new SeasonProductOrderTouristType();
                    orderTouristType.setSeasonOrderId(id);
                    orderTouristType.setPassengerId(1);
                    orderTouristType.setPassengerNum(adult);
                    list.add(orderTouristType);
                }
                Integer child = req.getChild();
                if(null != child){
                    SeasonProductOrderTouristType orderTouristType = new SeasonProductOrderTouristType();
                    orderTouristType.setSeasonOrderId(id);
                    orderTouristType.setPassengerId(2);
                    orderTouristType.setPassengerNum(child);
                    list.add(orderTouristType);
                }
                seasonProductOrderTouristTypeMapper.insertBatchSomeColumn(list);
            }

            sendOrderToAppUser(seasonOrder.getId());
        }
        return Result.success(seasonOrderId);
    }

    public BigDecimal getPackageProduct(SeasonOrderReq req, Integer channelType, Long relId) {
        FixedSeasonDetailsDTO fixedSeason = productService.getFixedProductBaseDTO(req.getProductId());
        log.info("进入填写订单计算价格的接口");
        log.info("getSeasonPackageProductFlag "+req.getSeasonPackageProductFlag());

        BigDecimal big = BigDecimal.ZERO;
        try {
            String str[] = req.getSeasonPackageProductFlag().split(",");

            log.info("split getSeasonPackageProductFlag "+str.toString());
            LocalDate departureDate = req.getStartDate();

            int i = 0;
            for (String productFlag : str) {

                i++;
                log.info("=========================执行循环第"+i+"次开始=========================");
                log.info("productFlag "+ productFlag);
                SeasonIndividualType productFlagEnum = SeasonIndividualType.getEnumType(productFlag);
                switch (productFlagEnum) {
                    //机票
                    case AIR:
                        List<SeasonProductOrderAirDTO> airList = req.getAirList();
                        if (airList != null && airList.size() > 0) {
                            for (SeasonProductOrderAirDTO item : airList) {
                                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                                    departureDate = DateUtil.getNextNDay(departureDate, Integer.parseInt(req.getTravelDays()));
                                }
                                PackageProductCostDTO result = seasonFixedProductPackageAirService.getAirProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                                BigDecimal adult = result.getCostPrice().multiply(new BigDecimal(req.getAdult()));
                                BigDecimal child = result.getChildPrice().multiply(new BigDecimal(req.getChild()));
                                big = big.add(adult).add(child);


                            }

                            log.info(i+"加完了机票后的价格为"+big);
                        }

                        break;
                        //酒店+
                    case HOTEL:
                        List<SeasonProductOrderHotelDTO> hotelList = req.getHotelList();
                        if (hotelList != null && hotelList.size() > 0) {
                            for (SeasonProductOrderHotelDTO item : hotelList) {
                                log.info("酒店产品ID "+item.getProductId());
                                log.info("departureDate "+departureDate);
                                log.info("req.getTravelNights() "+req.getTravelNights());
                                log.info("relId "+relId);
                                log.info("channelType "+channelType);
                                PackageProductCostDTO result = seasonFixedProductPackageHotelService.getHotelProductPrice(item.getProductId(), departureDate, DateUtil.getNextNDay(departureDate, req.getTravelNights()), fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                                big = big.add(result.getCostPrice().multiply(new BigDecimal(req.getRoomNum())));


                            }

                            log.info("加完了酒店后的价格为"+big);
                        }
                        break;
                        //巴士
                    case BUS:
                        List<SeasonProductOrderBusDTO> busList = req.getBusList();
                        if (busList != null && busList.size() > 0) {
                            for (SeasonProductOrderBusDTO item : busList) {
                                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                                    departureDate = DateUtil.getNextNDay(departureDate, Integer.parseInt(req.getTravelDays()));
                                }
                                PackageProductCostDTO result = seasonFixedProductPackageBusService.getBusProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                                BigDecimal adult = result.getCostPrice().multiply(new BigDecimal(req.getAdult()));
                                BigDecimal child = result.getChildPrice().multiply(new BigDecimal(req.getChild()));
                                big = big.add(adult).add(child);


                            }

                            log.info("加完了巴士后的价格为"+big);
                        }

                        break;
                        //船票
                    case SHIP:
                        List<SeasonProductOrderShipDTO> shipList = req.getShipList();
                        if (shipList != null && shipList.size() > 0) {
                            for (SeasonProductOrderShipDTO item : shipList) {
                                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                                    departureDate = DateUtil.getNextNDay(departureDate, Integer.parseInt(req.getTravelDays()));
                                }
                                PackageProductCostDTO result = seasonFixedProductPackageShipService.getShipProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                                BigDecimal adult = result.getCostPrice().multiply(new BigDecimal(req.getAdult()));
                                BigDecimal child = result.getChildPrice().multiply(new BigDecimal(req.getChild()));
                                big = big.add(adult).add(child);


                            }

                            log.info("加完了船票后的价格为"+big);
                        }
                        break;
                        //火车
                    case TRAIN:
                        List<SeasonProductOrderTrainDTO> trainList = req.getTrainList();
                        if (trainList != null && trainList.size() > 0) {
                            for (SeasonProductOrderTrainDTO item : trainList) {
                                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                                    departureDate = DateUtil.getNextNDay(departureDate, Integer.parseInt(req.getTravelDays()));
                                }
                                PackageProductCostDTO result = seasonFixedProductPackageTrainService.getTrainProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                                BigDecimal adult = result.getCostPrice().multiply(new BigDecimal(req.getAdult()));
                                BigDecimal child = result.getChildPrice().multiply(new BigDecimal(req.getChild()));
                                big = big.add(adult).add(child);


                            }

                            log.info("加完了火车后的价格为"+big);
                        }
                        break;
                        //景点门票
                    case SCENIC:
                        List<SeasonProductOrderScenicDTO> scenicList = req.getScenicList();
                        if (scenicList != null && scenicList.size() > 0) {
                            for (SeasonProductOrderScenicDTO item : scenicList) {
                                PackageProductCostDTO result = seasonFixedProductPackageScenicService.getScenicProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode(), item.getAttr1Id(), item.getAttr2Id());
                                big = big.add(result.getCostPrice().multiply(new BigDecimal(req.getAdult()+req.getChild())));


                            }
                            log.info("加完了门票后的价格为"+big);
                        }
                        break;
                        //当地玩乐
                    case LOCALFUN:
                        List<SeasonProductOrderLocalFunDTO> localFunList = req.getLocalFunList();
                        if (localFunList != null && localFunList.size() > 0) {
                            for (SeasonProductOrderLocalFunDTO item : localFunList) {
                                PackageProductCostDTO result = seasonFixedProductPackageLocalFunService.getLocalFunProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode(), item.getAttr1Id(), item.getAttr2Id());
                                big = big.add(result.getCostPrice().multiply(new BigDecimal(req.getAdult()+req.getChild())));
                            }

                            log.info("加完了当地玩乐后的价格为"+big);
                        }
                        break;
                        //商品
                    case COMMODITY:
                        List<SeasonProductOrderCommodityDTO> commodityList = req.getCommodityList();
                        if (commodityList != null && commodityList.size() > 0) {
                            for (SeasonProductOrderCommodityDTO item : commodityList) {
                                PackageProductCostDTO result = seasonFixedProductPackageCommodityService.getCommodityProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(),  SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode(), item.getAttr1Id(), item.getAttr2Id());
                                big = big.add(result.getCostPrice().multiply(new BigDecimal(req.getAdult()+req.getChild())));
                            }

                            log.info("加完了商品后的价格为"+big);
                        }
                        break;
                    default:
                        log.info("未识别任何品类");
                        break;
                }

                log.info("=========================执行循环第"+i+"次结束=========================");
            }
            if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == req.getProductType()) {//如果是固定需要加幅价格
                big = seasonFixedProductPackageService.getFixedSeasonAdjust(big, relId, req.getStartDate(), req.getProductId(), channelType);

                log.info("加完了加幅后的价格为"+big);
            }
        } catch (Exception e) {
            big = BigDecimal.ZERO;
            log.error("计算价格发生异常", e);
        }

        return big;
    }

    public BigDecimal getPackageProduct(AppCalculatePriceReq req, Integer channelType, Long relId) {
        FixedSeasonDetailsDTO fixedSeason = productService.getFixedProductBaseDTO(req.getProductId());
        BigDecimal big = BigDecimal.ZERO;
        LocalDate departureDate = req.getStartDate();
        List<AppCommonCalculatePriceReq> airList = req.getAirList();
        if (airList != null && airList.size() > 0) {
            for (AppCommonCalculatePriceReq item : airList) {
                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                    departureDate = DateUtil.getNextNDay(departureDate, fixedSeason.getTravelDays());
                }
                PackageProductCostDTO result = seasonFixedProductPackageAirService.getAirProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                BigDecimal adult = null;
                BigDecimal child = null;
                if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == req.getProductType()) {//如果是固定需要加幅价格
                    adult = result.getCostPrice().multiply(new BigDecimal(req.getAdult()));
                    child = result.getChildPrice().multiply(new BigDecimal(req.getChild()));
                } else {
                    adult = result.getCostPrice().multiply(new BigDecimal(item.getAdult()));
                    child = result.getChildPrice().multiply(new BigDecimal(item.getChild()));
                }
                big = big.add(adult).add(child);
            }

            log.info("加完了机票后的价格为"+big);
        }

        List<AppCommonCalculatePriceReq> hotelList = req.getHotelList();
        if (hotelList != null && hotelList.size() > 0) {
            for (AppCommonCalculatePriceReq item : hotelList) {
                PackageProductCostDTO result = seasonFixedProductPackageHotelService.getHotelProductPrice(item.getProductId(), departureDate, DateUtil.getNextNDay(departureDate, fixedSeason.getTravelNights()), fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                BigDecimal costPrice = null;
                if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == req.getProductType()) {//如果是固定需要加幅价格
                    costPrice = result.getCostPrice().multiply(new BigDecimal(req.getRoomNum()));
                } else {
                    costPrice = result.getCostPrice().multiply(new BigDecimal(req.getRoomNum()));
                }
                big = big.add(costPrice);
            }

            log.info("加完了酒店后的价格为"+big);
        }
        //巴士
        List<AppCommonCalculatePriceReq> busList = req.getBusList();
        if (busList != null && busList.size() > 0) {
            for (AppCommonCalculatePriceReq item : busList) {
                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                    departureDate = DateUtil.getNextNDay(departureDate, fixedSeason.getTravelDays());
                }
                PackageProductCostDTO result = seasonFixedProductPackageBusService.getBusProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                BigDecimal adult = null;
                BigDecimal child = null;
                if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == req.getProductType()) {//如果是固定需要加幅价格
                    adult = result.getCostPrice().multiply(new BigDecimal(req.getAdult()));
                    child = result.getChildPrice().multiply(new BigDecimal(req.getChild()));
                } else {
                    adult = result.getCostPrice().multiply(new BigDecimal(item.getAdult()));
                    child = result.getChildPrice().multiply(new BigDecimal(item.getChild()));
                }
                big = big.add(adult).add(child);
            }

            log.info("加完了巴士后的价格为"+big);
        }
        //船票

        List<AppCommonCalculatePriceReq> shipList = req.getShipList();
        if (shipList != null && shipList.size() > 0) {
            for (AppCommonCalculatePriceReq item : shipList) {
                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                    departureDate = DateUtil.getNextNDay(departureDate, fixedSeason.getTravelDays());
                }
                PackageProductCostDTO result = seasonFixedProductPackageShipService.getShipProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                BigDecimal adult = null;
                BigDecimal child = null;
                if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == req.getProductType()) {
                    adult = result.getCostPrice().multiply(new BigDecimal(req.getAdult()));
                    child = result.getChildPrice().multiply(new BigDecimal(req.getChild()));
                } else {
                    adult = result.getCostPrice().multiply(new BigDecimal(item.getAdult()));
                    child = result.getChildPrice().multiply(new BigDecimal(item.getChild()));
                }
                big = big.add(adult).add(child);
            }

            log.info("加完了船票后的价格为"+big);
        }

        //火车
        List<AppCommonCalculatePriceReq> trainList = req.getTrainList();
        if (trainList != null && trainList.size() > 0) {
            for (AppCommonCalculatePriceReq item : trainList) {
                if (SeasonType.JOURNEY_TYPE_RETURN.getKey().equals(item.getTripType())) {
                    departureDate = DateUtil.getNextNDay(departureDate, fixedSeason.getTravelDays());
                }
                PackageProductCostDTO result = seasonFixedProductPackageTrainService.getTrainProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode());
                BigDecimal adult = result.getCostPrice().multiply(new BigDecimal(item.getAdult()));
                BigDecimal child = result.getChildPrice().multiply(new BigDecimal(item.getChild()));
                big = big.add(adult).add(child);
            }

            log.info("加完了火车票后的价格为"+big);
        }
        //景点门票
        List<AppCommonCalculatePriceReq> scenicList = req.getScenicList();
        if (scenicList != null && scenicList.size() > 0) {
            for (AppCommonCalculatePriceReq item : scenicList) {
                PackageProductCostDTO result = seasonFixedProductPackageScenicService.getScenicProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode(), item.getAttr1Id(), item.getAttr2Id());
                BigDecimal costPrice = result.getCostPrice().multiply(new BigDecimal(req.getAdult()+req.getChild()));
                big = big.add(costPrice);
            }

            log.info("加完了门票后的价格为"+big);
        }
        //当地玩乐
        List<AppCommonCalculatePriceReq> localFunList = req.getLocalFunList();
        if (localFunList != null && localFunList.size() > 0) {
            for (AppCommonCalculatePriceReq item : localFunList) {
                PackageProductCostDTO result = seasonFixedProductPackageLocalFunService.getLocalFunProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode(), item.getAttr1Id(), item.getAttr2Id());
                BigDecimal costPrice = result.getCostPrice().multiply(new BigDecimal(req.getAdult()+req.getChild()));
                big = big.add(costPrice);
            }

            log.info("加完了当地玩乐后的价格为"+big);
        }
        //商品
        List<AppCommonCalculatePriceReq> commodityList = req.getCommodityList();
        if (commodityList != null && commodityList.size() > 0) {
            for (AppCommonCalculatePriceReq item : commodityList) {
                PackageProductCostDTO result = seasonFixedProductPackageCommodityService.getCommodityProductPrice(item.getProductId(), departureDate, fixedSeason.getChargeUserId(), SeasonType.OFFLINE_SELF_CHANNEL_TYPE.getCode(), item.getAttr1Id(), item.getAttr2Id());
                BigDecimal costPrice = result.getCostPrice().multiply(new BigDecimal(req.getAdult()+req.getChild()));
                big = big.add(costPrice);
            }

            log.info("加完了商品后的价格为"+big);
        }
        if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == req.getProductType()) {//如果是固定需要加幅价格
            big = seasonFixedProductPackageService.getFixedSeasonAdjust(big, relId, req.getStartDate(), req.getProductId(), channelType);
        }

        log.info("加完了加幅后的价格为"+big);
        return big;
    }

    @Override
    public List<SeasonOrderDTO> queryOrderDTOList(LocalDateTime recent, LocalDateTime now) {
        return EntityUtil.copyList(baseMapper.selectList(Wrappers.<SeasonOrder>lambdaQuery()
                .eq(SeasonOrder::getIsDeleted, IsDeletedCode.NO.getCode())
                .ge(SeasonOrder::getGmtCreate, recent)
                .le(SeasonOrder::getGmtCreate, now)),SeasonOrderDTO.class);
    }


    /* @MethodName: 保存套票 打包产品id
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/25 20:42
     **/
    private void saveSeasonPackageOrder(SeasonOrderReq req, Long userId, Long seasonOrderId) {
        //保存机票信息
        List<SeasonProductOrderAirDTO> airList = req.getAirList();
        if (CollectionUtils.isNotEmpty(airList)) {
            orderAirService.saveAirProduct(airList, userId, seasonOrderId);
        }

        //保存巴士票信息
        List<SeasonProductOrderBusDTO> busList = req.getBusList();
        if (CollectionUtils.isNotEmpty(busList)) {
            orderBusService.saveBusProduct(busList, userId, seasonOrderId);
        }

        //保存火车票信息
        List<SeasonProductOrderTrainDTO> trainList = req.getTrainList();
        if (CollectionUtils.isNotEmpty(trainList)) {
            orderTrainService.saveTrainProduct(trainList, userId, seasonOrderId);
        }

        //保存酒店信息
        List<SeasonProductOrderHotelDTO> hotelList = req.getHotelList();
        if (CollectionUtils.isNotEmpty(hotelList)) {
            orderHotelService.saveHotelProduct(hotelList, userId, seasonOrderId);
        }

        //保存景点门票信息
        List<SeasonProductOrderScenicDTO> scenicList = req.getScenicList();
        if (CollectionUtils.isNotEmpty(scenicList)) {
            orderScenicService.saveScenicProduct(scenicList, userId, seasonOrderId);
        }

        //保存船票订单信息
        List<SeasonProductOrderShipDTO> shipList = req.getShipList();
        if (CollectionUtils.isNotEmpty(shipList)) {
            orderShipService.saveShipProduct(shipList, userId, seasonOrderId);
        }

        //保存本地玩乐订单信息
        List<SeasonProductOrderLocalFunDTO> localFunList = req.getLocalFunList();
        if (CollectionUtils.isNotEmpty(localFunList)) {
            orderLocalFunService.saveLocalFunProduct(localFunList, userId, seasonOrderId);
        }

    }


    /* @MethodName: 核对订单
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/25 14:33
     **/
    @Transactional
    @Override
    public Result checkSeasonOrder(SeasonOrderReq req, TokenUser tokenUser) {
        Integer productType = req.getProductType();
        Long productId = req.getProductId();//
        FixedSeasonDetailsDTO fixedSeason = null;
        if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == productType) {//固定套票
            fixedSeason = productService.getFixedProductBaseDTO(productId);
            if (Objects.isNull(fixedSeason)) {
                return Result.failed(SystemError.SEASON_TICKET_20004);
            }
        }

        //保险费用
        BigDecimal insuranceAmountFlag = BigDecimal.ZERO;
        Integer insuranceNumberFlag = 0;
        //保险信息
        if (req.getBuyInsurance() == NumberConstant.ONE.getValue()) {
            List<SeasonOrderInsuranceDTO> insuranceDTOList = req.getSeasonOrderInsuranceDataList();
            if (CollectionUtil.isEmpty(insuranceDTOList)) {
                return Result.failed(SystemError.SEASON_TICKET_20013);
            }
            for (SeasonOrderInsuranceDTO insuranceDto : insuranceDTOList) {
                insuranceNumberFlag++;
                insuranceAmountFlag.add(insuranceDto.getInsurancePrice());//保险价格
            }
            boolean totalPriceFlag = insuranceAmountFlag.compareTo(req.getInsuranceAmount()) != 0;//金额
            boolean numFlag = insuranceNumberFlag != req.getInsuranceNumber();//保险数量

            if (totalPriceFlag || numFlag) {
                return Result.failed(SystemError.SEASON_TICKET_20015);
            }
        }
        BigDecimal seasonAmount = req.getSeasonAmount();//套票金额
        if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == productType) {//固定套票
            List<PassengerReq> passengerReqList = EntityUtil.copyList(req.getTrainList(), PassengerReq.class);
            //ProductCostReq costReq = new ProductCostReq(productId, req.getStartDate(), passengerReqList, req.getRoomNum(), req.getTravelNights(), fixedSeason.getPackageId(), req.getSeasonPackageProductFlag(), tokenUser.getId(), 1);
            //     BigDecimal seasonFixedPrice = seasonFixedProductPackageService.getSeasonProductPrice(costReq, tokenUser);
//            if (seasonAmount.compareTo(seasonFixedPrice) != 0) {
//                return Result.failed(SystemError.SEASON_TICKET_20016);
//            }
        }

        if (SeasonType.PRODUCT_DYNAMIC_TYPE.getCode() == productType) {//动态套票b
            //获取动态打包的产品的成本+加幅价
            //BigDecimal dynamicPrice = seasonSinglePriceService.getCheckDynamicPrice(req, tokenUser);
//            if (seasonAmount.compareTo(dynamicPrice) != 0) {
//                return Result.failed(SystemError.SEASON_TICKET_20016);
//            }
        }

        SeasonOrder seasonOrder = seasonOrderMapper.selectById(req.getOrderId());

        /**最晚付款时间为创建订单后30分钟*/
        seasonOrder.setPayExpireDate(LocalDateTime.now().plusMinutes(30));

        seasonOrderMapper.updateById(seasonOrder);

        return Result.success();
    }


    /* @MethodName: 锁定各个产品的库存
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/13 16:13
     **/
    private void treasuryLocks(Long seasonOrderId, SeasonOrderReq req, Long userId) {
        SeasonIndividualType productFlagEnum = SeasonIndividualType.getEnumType(req.getSeasonPackageProductFlag());
        //套票打包产品属性 ( 1:机票 2:酒店 3:巴士 4:船票 5:火车票 6:景点门票 7:当地玩乐) 多个以逗号分隔
        switch (productFlagEnum) {
            case AIR:
                orderAirService.lockInventoryAir(seasonOrderId, req, null);
                break;
            case HOTEL:
                //orderHotelService.playSupplierOrder(orderId, user);
                break;

            case BUS:
                //orderBusService.playSupplierOrder(orderId, user);
                break;

            case SHIP:
                // orderShipService.playSupplierOrder(orderId, user);
                break;

            case TRAIN:
                //orderTrainService.playSupplierOrder(orderId, user);
                break;

            case SCENIC:
                //orderScenicService.playSupplierOrder(orderId, user);

            case LOCALFUN:
                if (CollectionUtils.isNotEmpty(req.getLocalFunList())) {
                    SeasonProductOrderLocalFunDTO localFun = req.getLocalFunList().get(0);

                    //B端套票若无代理商只考虑自营渠道
//                    CustomDto customSelLine = iLocalFunProductService.getCustomSelLine(localFun.getProductId(), 1, userId,null);
//                    localFunProductSaleRecordService.operateStock(LocalFunStockReq.builder().orderId(seasonOrderId)
//                            .productId(localFun.getProductId()).attrId1(localFun.getAttr1Id()).attrId2(localFun.getAttr2Id())
//                            .num(localFun.getNumber()).userId(userId)
//                            //自营
//                            .channel(1).customName(customSelLine.getCustomName()).customId(customSelLine.getCustomId())
//                            .checkType(customSelLine.getCheckType())
//                            //线下
//                            .line(2).build());
                }
                break;
        }
    }

    /* @MethodName: 保存订单付款信息 付款成功
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/25 17:42
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result saveOrderPay(List<SeasonOrderPayReq> reqList, Long userId) {
        if (CollectionUtils.isEmpty(reqList)) {
            return Result.failed(SystemError.SEASON_TICKET_20018);
        }
        Long orderId = reqList.get(0).getOrderId();
        SeasonOrder order = getById(orderId);
        Integer productType = order.getProductType();
        if (userId == null || userId == 0L) {
            DispatchOrderRuleGetUserReq dispatchOrderRuleGetUserReq = new DispatchOrderRuleGetUserReq();
            dispatchOrderRuleGetUserReq.setBusinessTypeId(SeasonType.PRODUCT_FIXED_TYPE.getCode() == productType ? SystemBusinessType.FIXED_PACKAGE_TICKET.getCode() : SystemBusinessType.DYNAMIC_PACKAGE_TICKET.getCode());
            dispatchOrderRuleGetUserReq.setCompanyType(CompanyType.HK_CT.getCode());
            Result<Long> userIdResult = dispatchOrderRuleService.getDispatchUserId(dispatchOrderRuleGetUserReq);
            if (userIdResult.isSuccess()) {
                userId = userIdResult.getData();
            }
        }
        //获取当前用户信息
        UserDTO user = iSysUserService.getByUserId(userId);
        TokenUser tokenUser = EntityUtil.copy(user, TokenUser.class);

        if (Objects.isNull(order)) {
            return Result.failed(SystemError.SEASON_TICKET_20017);
        }
        LocalDateTime now = LocalDateTime.now();
//        if (now.isAfter(order.getPayExpireDate())) {
//            // 支付超时
//            new BusinessException(SystemError.SEASON_TICKET_20019);
//        }
        order.setPaymentStatus(OrderPaymentStatus.ALREADY_PAYMENT.getCode());//已付款
        //预定状态
        order.setScheduledStatus(OrderScheduledStatus.CONFIRM_RESERVE.getCode());//待预定
        order.setModifiedId(user.getId());
        order.setGmtModified(now);
        /**
         * 根据总价计算应收金额，减去会员积分和优惠券
         */
        //优惠总金额
        BigDecimal totalCouponAmount = BigDecimal.ZERO;
        //银行总优惠
        BigDecimal totalBankPreferenceHk = BigDecimal.ZERO;
        BigDecimal amountCountHKD = BigDecimal.ZERO;//订单金额(港币)=实收金额+积分抵扣+优惠券
        //使用积分
        Integer points = order.getUsingPoints();
        if (points != null && points > 0) {// 使用积分
            //积分抵扣金额    如果有积分优惠 需要保存一条收款记录
            BigDecimal pointsAmount = collectionService.userPoints(order.getId(), tokenUser);
            totalCouponAmount.add(pointsAmount);//添加积分优惠
        }
        if (StringUtils.isNotBlank(order.getCouponCode())) {// 使用推广码
            //积分抵扣金额    如果有积分优惠 需要保存一条收款记录
            OperatePromotionQueryReq operatePromotionQueryReq = new OperatePromotionQueryReq();
            Result<OperatePromotionQueryDTO> promotionQuery = iOperatePromotionService.query(operatePromotionQueryReq);
            if (promotionQuery.isSuccess()) {
                totalCouponAmount.add(promotionQuery.getData().getReductionAmount());//添加推广码
            }
        }
        List<BillAddCollectionReq> billAddCollectionReqList = new LinkedList<>();
        List<SeasonOrderCollection> seasonOrderCollectionList = EntityUtil.copyList(reqList, SeasonOrderCollection.class);
        List<SeasonOrderCollection> collectionList = new LinkedList<>();
        for (SeasonOrderCollection collection : seasonOrderCollectionList) {
            BillAddCollectionReq req = new BillAddCollectionReq();
            String collectionNumber = SeasonOrderManager.getCollectionNumber();
            req.setBillNumber(collectionNumber);
            req.setBusinessType(SystemBusinessType.FIXED_PACKAGE_TICKET.getCode());
            req.setCollectionWayId(collection.getCollectionWayId());
            req.setCollectionWayName(collection.getCollectionWay());
            req.setCollectionTypeId(CollectionTypeIdCode.FULL.getCode());
            req.setCollectionTypeName(CollectionTypeIdCode.FULL.getMsg());
            req.setCollectionAmount(collection.getCollectionAmount());
            req.setCurrencyId(collection.getCurrencyId());
            req.setCurrencyName(collection.getCurrency());
            //待定
            req.setCollectionVoucherJsonList(null);
            req.setExchangeRate(collection.getExchangeRate());
            req.setCollectionTime(LocalDateTime.now());
            req.setSaleOrderNumber(order.getOrderNumber());
            req.setSaleOrderId(order.getId());
            req.setProductId(Arrays.asList(order.getProductId()));
            req.setProductNumber(order.getProductName());
            req.setProductName(order.getProductName());
            req.setSaleUserId(user.getId());
            req.setSaleOrderNumber(user.getUsername());
            req.setSaleDeptId(user.getDeptId());
            req.setUserId(user.getId());
            //资源信息
            req.setResourceInfo(null);
            billAddCollectionReqList.add(req);
            //获取门市汇率
            BigDecimal rate = getCrmExchangeRateById(collection.getCurrencyId());
            collection.setExchangeRate(rate.doubleValue());//汇率
            collection.setCollectionNumber(collectionNumber);
            BigDecimal bankPreference;
            //用银联优惠
            if (collection.getIsUnionpayDiscount() != null && collection.getIsUnionpayDiscount() == 1) {
                // 使用银联优惠
                if (order.getUsingPoints() != null || order.getCouponCode() != null) {
                    //使用了会员积分或优惠券，无法使用银联优惠
                    throw new BusinessException(SystemError.AIREXPRESS_ORDER_60025);
                }
                //银联优惠操作，返回折扣的金额
                bankPreference = getAmountByBankReference(order, collection, tokenUser);
                collection.setDiscountAmount(bankPreference);
                totalBankPreferenceHk.add(bankPreference);
            }
            amountCountHKD.add(collection.getCollectionAmount().multiply(rate));
            collection.setOrderId(orderId);
            collection.setStatus(OrderCollectionStatus.UN_REJECT.getCode());
            collection.setCreateId(user.getId());
            collection.setId(SnowflakeIdWorker.nextId());
            //销售人员
            collection.setSalerId(user.getId());
            collection.setSalerName(user.getUsername());
            collection.setGmtCreate(now);
            collection.setIsDeleted(IsDeletedCode.NO.getCode());
            //添加对应的支付方式
            collectionList.add(collection);
        }
        totalCouponAmount.add(totalBankPreferenceHk);//添加总金额
        //添加优惠的金额
        order.setTotalCouponAmount(totalCouponAmount);
        //应收的金额
        order.setReceivableAmount(order.getOrderAmount().subtract(totalCouponAmount));
        // 校验应收价格
        if (amountCountHKD.compareTo(order.getReceivableAmount()) <= 0) {
            // 支付价格小于应收价格
            throw new BusinessException(SystemError.SEASON_TICKET_20020);
        }
        seasonOrderCollectionMapper.insertBatchSomeColumn(collectionList);

        //修改金额
        this.updateById(order);
        //保存一条收据记录
        Result seasonOrderReceiptResult = seasonOrderReceiptService.addReceipt(order.getId(), tokenUser);
        SeasonOrderReceipt seasonOrderReceipt = (SeasonOrderReceipt) seasonOrderReceiptResult.getData();
        //如果有保险  保险下单
        insuranceService.placeAnOrder(order.getId(), tokenUser);
        //对应下各个单项的订单
        placeAnOrder(order, tokenUser);
        //财务收款
        Result result = financeBillService.addCollection(billAddCollectionReqList);
        if (result.getCode() != 0) {
            throw new BusinessException(SystemError.AIR_ORDER_15015, result.getMsg());
        }
        LevyRequest request = new LevyRequest();
        request.setReceiptNumber(seasonOrderReceipt.getReceiptNo());
        request.setDepartureDate(DateUtil.fmtDay(order.getDepartDate()));
        request.setPremiumReceived(order.getStampTaxAmount().toString());
        request.setUserId(order.getSalesmanId());
        request.setNameOfTravelerPayer(order.getSalesmanName());
        request.setLast4DigitOfContactPhoneNumber(order.getContactMobile().substring(order.getContactMobile().length() - 4));
        if (order.getProductType() == SeasonType.PRODUCT_FIXED_TYPE.getCode()) {
            request.setBusinessType(SystemBusinessType.FIXED_PACKAGE_TICKET.getCode());
        } else {
            request.setBusinessType(SystemBusinessType.DYNAMIC_PACKAGE_TICKET.getCode());
        }

        levyService.levyEFrank(request);
        updateStatusToAppUser(order.getId());
        return Result.success();
    }

    /* @MethodName: 下各个单项的单
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/7 11:28
     **/
    private void placeAnOrder(SeasonOrder order, TokenUser user) {
        String seasonPackageProductFlag = order.getSeasonPackageProductFlag();
        Long orderId = order.getId();
        //如果是 固定套票 生成自己的订单 下供应商预定单  如果是动态套票生成各自的订单
        boolean flag = SeasonType.PRODUCT_FIXED_TYPE.getCode() == order.getProductType();//表示是固定套票
        if (StringUtils.isNotBlank(seasonPackageProductFlag)) {
            //转化订单顺序
            List<Integer> flagList = SeasonOrderManager.conversionOrder(seasonPackageProductFlag);
            if (null != flagList) {
                //旅客信息 付款方式的枚举类PayRefundMethod
                List<SeasonOrderTouristDataDTO> touristList = seasonOrderTouristService.getTouristList(orderId);
                List<SeasonOrderInsuranceDTO> insuranceList = seasonOrderTouristService.getOrderInsurance(orderId);
                Map<String, Object> map = new HashMap<>();
                map.put("failFlag", false);//添加失败标识默认是成功的没有失败的。
                map.put("couponFlag", false);//添加推广码标识默认是没有使用的
                map.put("seasonOrder", order);//放入订单信息
                BigDecimal integralDeduction = BigDecimal.ZERO;
                if (null != order.getUsingPoints() && order.getUsingPoints() > 0) {
                    integralDeduction = new BigDecimal(order.getUsingPoints()).divide(new BigDecimal(100));
                }
                map.put("usingPoints", integralDeduction);//添加积分标识默认是没有使用的
                map.put("isFinal", false);//添加是否最后一个
                map.put("isInsurance", false);//是否保险最后一个
                //获取支付方式
                List<SeasonOrderPayDTO> payList = collectionService.getCollectionListById(orderId);
                for (int i = 0; i < flagList.size(); i++) {
                    Integer product = flagList.get(i);
                    if (i == flagList.size() - 1) {
                        map.put("isFinal", true);//添加积分标识默认是没有使用的
                    }
                    //对应下各个单项的订单
                    //套票打包产品属性 ( 1:机票 2:酒店 3:巴士 4:船票 5:火车票 6:景点门票 7:当地玩乐) 多个以逗号分隔
                    SeasonIndividualType productFlagEnum = SeasonIndividualType.getEnumType(String.valueOf(product));
                    switch (productFlagEnum) {
                        case AIR:
                            if (flag) { //固定套票的 走内部挂账 下单
                                orderAirService.playInternalOrder(orderId, user, touristList);
                            } else {//动态套票 下各个单项的单
                                orderAirService.playAirOrder(orderId, user, payList, touristList);
                            }
                            break;
                        case HOTEL:
                            if (flag) {//固定套票的 走内部挂账 下单
                                orderHotelService.playInternalOrder(orderId, user);
                            } else {//动态套票 下各个单项的单
                                orderHotelService.playHotelOrder(orderId, user, payList);
                            }
                            break;
                        case BUS:
                            if (flag) {//固定套票的 走内部挂账 下单
                                orderBusService.playInternalOrder(orderId, user);
                            } else {//动态套票 下各个单项的单
                                orderBusService.playBusOrder(orderId, user, payList);
                            }
                            break;
                        case SHIP:
                            if (flag) {//固定套票的 走内部挂账 下单
                                orderShipService.playInternalOrder(orderId, user);
                            } else {//动态套票 下各个单项的单
                                orderShipService.playShipOrder(orderId, user, payList);
                            }
                            break;
                        case TRAIN:
                            if (flag) {//火车票固定套票的 走内部挂账 下单
                                orderTrainService.playInternalOrder(orderId, user);
                            } else {//动态套票 下各个单项的单
                                orderTrainService.playTrainOrder(user, payList, touristList, map);
                            }
                            break;
                        case SCENIC:
                            if (flag) {//景点固定套票的 走内部挂账 下单
                                orderScenicService.playInternalOrder(orderId, user, touristList);
                            } else {//动态套票 下各个单项的单
                                orderScenicService.playScenicOrder(user, payList, touristList, map);
                            }
                            break;
                        case LOCALFUN:
                            if (flag) {//固定套票的 走内部挂账 下单
                                orderLocalFunService.playInternalOrder(orderId, user, touristList);
                            } else {//动态套票 下各个单项的单
                                orderLocalFunService.playLocalFunOrder(orderId, user, payList, touristList);
                            }
                            break;
                        case COMMODITY:
                            if (flag) {//固定套票的 走内部挂账 下单
                                orderCommodityService.playInternalOrder(orderId, user, touristList);
                            } else {//动态套票 下各个单项的单
                                orderCommodityService.playCommodityOrder(orderId, user, payList, touristList);
                            }
                            break;
                    }
                }
                boolean failFlag = (boolean) map.get("failFlag");//获取失败标识
                if (failFlag) {
                    //失败之后需要去取消订单或者退款
                    //景点退款
                    Object scenicPayOrderObj = map.get("scenicPayOrderResult");
                    if (null != scenicPayOrderObj) {
                        Result scenicPayOrderResult = (Result) scenicPayOrderObj;
                        List<Long> scenicOrderIds = (List<Long>) map.get("scenicOrderIds");
                        if (scenicPayOrderResult.isSuccess()) {
                            for (Long scenicOrderId : scenicOrderIds) {
                                Scenic0rderRefundDetailReq scenic0rderRefundDetailReq = new Scenic0rderRefundDetailReq();
                                scenic0rderRefundDetailReq.setOrderId(scenicOrderId.toString());
                                scenic0rderRefundDetailReq.setCancelReason(SystemError.SEASON_TICKET_20037.getMsg());
                                scenicOrderService.cancelScenicOrderRefund(scenic0rderRefundDetailReq, user);
                                QueryWrapper<SeasonProductOrderScenic> queryWrapper = new QueryWrapper<>();
                                queryWrapper.eq("order_id", scenicOrderId);
                                queryWrapper.eq("is_deleted", IsDeletedCode.NO.getCode());
                                List<SeasonProductOrderScenic> spocList = orderScenicMapper.selectList(queryWrapper);
                                if (null != spocList && spocList.size() > 0) {
                                    SeasonProductOrderScenic scenic = spocList.get(0);
                                    scenic.setScheduledStatus(3);
                                    scenic.setCancelStatus(4);
                                    orderScenicMapper.updateById(scenic);
                                }
                            }
                        } else {
                            //景点取消下单
                            Object scenicAddOrderObj = map.get("scenicAddOrderResult");
                            if (null != scenicAddOrderObj) {
                                Result scenicAddOrderResult = (Result) scenicAddOrderObj;
                                if (scenicAddOrderResult.isSuccess()) {
                                    for (Long scenicOrderId : scenicOrderIds) {
                                        Scenic0rderCancelReq scenic0rderCancelReq = new Scenic0rderCancelReq();
                                        scenic0rderCancelReq.setOrderId(scenicOrderId.toString());
                                        scenic0rderCancelReq.setCancelReason(SystemError.SEASON_TICKET_20037.getMsg());
                                        scenicOrderService.cancelScenicOrder(scenic0rderCancelReq, user);
                                    }
                                }
                            }
                        }
                    }
                    //火车票退款
                    Object trainPayOrderObj = map.get("trainPayOrderResult");
                    if (null != trainPayOrderObj) {
                        Result trainPayOrderResult = (Result) trainPayOrderObj;
                        List<Long> trainOrderIds = (List<Long>) map.get("trainOrderIds");
                        if (trainPayOrderResult.isSuccess()) {
                            for (Long trainOrderId : trainOrderIds) {
                                TrainCancelOrderReq cancelOrderReq = new TrainCancelOrderReq();
                                cancelOrderReq.setOrderId(trainOrderId);
                                cancelOrderReq.setRemark(SystemError.SEASON_TICKET_20037.getMsg());
                                cancelOrderReq.setRefundReason(SystemError.SEASON_TICKET_20037.getMsg());
                                trainOrderService.cancelOrder(cancelOrderReq, user);
                                QueryWrapper<SeasonProductOrderTrain> queryWrapper = new QueryWrapper<>();
                                queryWrapper.eq("order_id", trainOrderId);
                                queryWrapper.eq("is_deleted", IsDeletedCode.NO.getCode());
                                List<SeasonProductOrderTrain> trainList = orderTrainMapper.selectList(queryWrapper);
                                if (null != trainList && trainList.size() > 0) {
                                    SeasonProductOrderTrain train = trainList.get(0);
                                    train.setScheduledStatus(3);
                                    train.setCancelStatus(4);
                                    orderTrainMapper.updateById(train);
                                }
                            }
                        } else {
                            //火车票取消下单
                            Object trainAddOrderObj = map.get("trainAddOrderResult");
                            if (null != trainAddOrderObj) {
                                Result trainAddOrderResult = (Result) trainAddOrderObj;
                                if (trainAddOrderResult.isSuccess()) {
                                    for (Long trainOrderId : trainOrderIds) {
                                        trainOrderService.confirmRefund(trainOrderId, user.getId());
                                    }
                                }
                            }
                        }
                    }
                    //抛出异常
                    throw new BusinessException(SystemError.SEASON_TICKET_20036);
                }
            }
        }

    }

    /* @MethodName: 订单中心 套票订单搜索
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/29 10:36
     **/
    @Override
    public Result<PageResponse<SeasonSearchOrderDTO>> searchSeasonOrder(SearchSeasonOrderReq req, TokenUser user) {
        IPage<SeasonSearchOrderDTO> page = new Page<>(req.getPageNo(), req.getPageSize());
        //搜索固定套票列表
        page = seasonOrderMapper.searchSeasonOrderList(req, page);
        List<SeasonSearchOrderDTO> records = page.getRecords();
        records.forEach(item->{
            Long productId = item.getProductId();
            FixedSeasonDetailsDTO fixedProductBaseDTO = iSeasonFixedProductService.getFixedProductBaseDTO(productId);
            item.setSeasonTypeName(fixedProductBaseDTO.getSeasonTypeName());
        });
        PageResponse<SeasonSearchOrderDTO> result = new PageResponse<>(page.getRecords(), page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(), page.getCurrent(), page.getSize());
        return Result.success(result);
    }

    /* @MethodName: 获取订单详情
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/29 16:30
     **/
    private List<SeasonProductOrderTouristType> getSeasonProductOrderTouristTypeByOrderId(Long id){
        QueryWrapper<SeasonProductOrderTouristType> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(SeasonProductOrderTouristType::getSeasonOrderId,id);
        List<SeasonProductOrderTouristType> list  = seasonProductOrderTouristTypeMapper.selectList(wrapper);
        return list;
    }
    @Override
    public SeasonSearchOrderDTO getOrderInfoById(Long id) {
        SeasonSearchOrderDTO detailsDTO = getOrderById(id);
        List<SeasonProductOrderTouristType> typeList = getSeasonProductOrderTouristTypeByOrderId(id);
        typeList.forEach(item->{
            if(item.getPassengerId()==1)detailsDTO.setAdult(item.getPassengerNum());
            if(item.getPassengerId()==2)detailsDTO.setChild(item.getPassengerNum());
        });
        if (!Objects.isNull(detailsDTO)) {
            Integer productTypeFlag = detailsDTO.getProductType();
            String seasonTypeName = "";
            StringBuffer travelDays = new StringBuffer("");
            LocalDate backRoundDate = null;//返程日期
            String travel = "";
            Integer backTerms = 0;
            String bookingInformation = "";
            detailsDTO.setSeasonOrderInsuranceDataList(getSeasonOrderInsuranceDTOByOrderId(detailsDTO.getId()));
            if(OrderCancelStatus.ALREADY_REFUND.getCode().equals(detailsDTO.getCancelStatus())){
                SeasonOrderRefund seasonOrderRefund = seasonOrderRefundMapper.selectOne(Wrappers.<SeasonOrderRefund>lambdaQuery()
                        .eq(SeasonOrderRefund::getOrderId, detailsDTO.getId())
                        .eq(SeasonOrderRefund::getIsDeleted, IsDeletedCode.NO.getCode()));
                detailsDTO.setRefundReason(seasonOrderRefund.getRefundReason());
            }
            //固定套票
            if (SeasonType.PRODUCT_FIXED_TYPE.getCode() == productTypeFlag) {
                Long fixedProductId = detailsDTO.getProductId();
                FixedSeasonDetailsDTO fixedSeason = productService.getFixedProductBaseDTO(fixedProductId);
                if (fixedSeason != null) {
                    seasonTypeName = fixedSeason.getSeasonTypeName();
                    travel = fixedSeason.getDepCityName() + "到" + fixedSeason.getArrCityName();
                    if (null != detailsDTO.getDepartDate()) {
                        backRoundDate = detailsDTO.getDepartDate().plusDays(fixedSeason.getTravelDays());
                    }
                    travelDays.append(fixedSeason.getTravelDays()).append("天").append(fixedSeason.getTravelNights()).append("晚");
                    backTerms = fixedSeason.getBackTerms();
                    bookingInformation = fixedSeason.getBookingInformation();
                }
            }
            detailsDTO.setBackTerms(backTerms);
            detailsDTO.setBackRoundDate(backRoundDate);
            detailsDTO.setSeasonTypeName(seasonTypeName);
            detailsDTO.setTravel(travel);
            detailsDTO.setTravelDays(travelDays.toString());
            detailsDTO.setBookingInformation(bookingInformation);
            //套票打包产品属性 ( 1:机票 2:酒店 3:巴士 4:船票 5:火车票 6:景点门票 7:当地玩乐) 多个以逗号分隔
            String str[] = detailsDTO.getSeasonPackageProductFlag().split(",");
            for (String productFlag : str) {
                SeasonIndividualType productFlagEnum = SeasonIndividualType.getEnumType(productFlag);
                switch (productFlagEnum) {
                    case AIR:
                        List<SeasonProductOrderAirDTO> airDTOList = orderAirService.getOrderAirList(id);
                        detailsDTO.setAirList(airDTOList);
                        break;
                    case HOTEL:
                        List<SeasonProductOrderHotelDTO> hotelDTOList = orderHotelService.getOrderHotelList(id);
                        detailsDTO.setHotelList(hotelDTOList);
                        break;
                    case BUS:
                        List<SeasonProductOrderBusDTO> busDTOList = orderBusService.getOrderBusList(id);
                        busDTOList.forEach(item->{
                            Long productId = item.getProductId();
                            BusProductDTO busProductDTO = iBusProductService.queryDetail(productId);
                            BeanUtils.copyProperties(busProductDTO,item);
                        });
                        detailsDTO.setBusList(busDTOList);
                        break;
                    case SHIP:
                        List<SeasonProductOrderShipDTO> shipDTOList = orderShipService.getOrderShipList(id);
                        detailsDTO.setShipList(shipDTOList);
                        break;
                    case TRAIN:
                        List<SeasonProductOrderTrainDTO> trainDTOList = orderTrainService.getOrderTrainList(id);
                        detailsDTO.setTrainList(trainDTOList);
                        break;
                    case SCENIC:
                        List<SeasonProductOrderScenicDTO> scenicDTOList = orderScenicService.getOrderScenicList(id);
                        scenicDTOList.forEach(item->{
                            Long productId = item.getProductId();
                            Result<ScenicProductListDTO> scenicProductListDTOResult = iScenicProductService.queryById(productId);
                            ScenicProductListDTO scenicProduct = scenicProductListDTOResult.getData();
                            BeanUtils.copyProperties(scenicProduct,item);
                        });
                        detailsDTO.setScenicList(scenicDTOList);
                        break;
                    case LOCALFUN:
                        List<SeasonProductOrderLocalFunDTO> localFunDTOList = orderLocalFunService.getOrderLocalFunList(id);
                        localFunDTOList.forEach(item->{
                            Long productId = item.getProductId();
                            LocalFunProductDetailReq localFunProductDetailReq = new LocalFunProductDetailReq();
                            localFunProductDetailReq.setId(productId);
                            LocalFunProductDetailByIdDTO localFunProduct = iLocalFunProductService.localFunProductDetailByIdDTO(localFunProductDetailReq).getData();
                            BeanUtils.copyProperties(localFunProduct,item);
                        });
                        detailsDTO.setLocalFunList(localFunDTOList);
                        break;
                    case COMMODITY:
                        List<SeasonProductOrderCommodityDTO> commodityList = orderCommodityService.getOrderCommodityList(id);
                        detailsDTO.setCommodityList(commodityList);
                        break;
                }
            }


        }
        return detailsDTO;
    }

    private List<SeasonOrderInsuranceDTO> getSeasonOrderInsuranceDTOByOrderId(Long id){
        List<SeasonOrderInsuranceDTO> seasonOrderInsuranceDataList = null;
        List<SeasonOrderInsurance> seasonOrderInsurances = seasonOrderInsuranceMapper.selectList(Wrappers.<SeasonOrderInsurance>lambdaQuery()
                .eq(SeasonOrderInsurance::getOrderId, id)
                .eq(SeasonOrderInsurance::getIsDeleted, IsDeletedCode.NO.getCode()));
        seasonOrderInsuranceDataList = seasonOrderInsurances.stream().map(item->{
            SeasonOrderInsuranceDTO seasonOrderInsuranceDTO = new SeasonOrderInsuranceDTO();
            BeanUtils.copyProperties(item,seasonOrderInsuranceDTO);
            return seasonOrderInsuranceDTO;
        }).collect(Collectors.toList());
        return seasonOrderInsuranceDataList;
    }

    private SeasonSearchOrderDTO getOrderById(Long id) {
        SearchSeasonOrderReq req = new SearchSeasonOrderReq();
        req.setId(id);
        IPage<SeasonSearchOrderDTO> page = new Page<>(req.getPageNo(), req.getPageSize());
        //根据订单id搜索固定套票列表
        SeasonSearchOrderDTO detailsDTO = null;
        page = seasonOrderMapper.searchSeasonOrderList(req, page);
        if (null != page && null != page.getRecords() && page.getRecords().size() > 0) {
            detailsDTO = page.getRecords().get(0);
        }
        return detailsDTO;
    }

    /* @MethodName: 获取订单须知信息
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/29 18:30
     **/
    @Override
    public SeasonProductReplenishDTO getProductReplenishInfo(Long productId) {
        FixedSeasonDetailsDTO fixedSeason = productService.getFixedProductBaseDTO(productId);
        if (!Objects.isNull(fixedSeason)) {
            SeasonProductReplenishDTO dto = new SeasonProductReplenishDTO();
            dto.setBookingInformation(fixedSeason.getBookingInformation());
            dto.setIncludesFee(fixedSeason.getIncludesFee());
            dto.setRemark(fixedSeason.getRemark());
            return dto;
        }


        return null;
    }

    /* @MethodName: 取消订单  直接取消掉 不走流程
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/30 9:04
     **/
    @Override
    public Result cancelOrder(SeasonOrderCancelReq req, TokenUser currentUser) {
        SeasonOrder order = seasonOrderMapper.selectById(req.getId());
        if (Objects.isNull(order)) {
            return Result.failed(SystemError.SEASON_TICKET_20021);
        }
        if (order.getPaymentStatus().intValue() != OrderPaymentStatus.UN_PAYMENT.getCode().intValue()) {
            return Result.failed(SystemError.SEASON_TICKET_20021);
        }
        //如果是 固定套票 需要查出改套票的 退改条款
        if (order.getProductType().intValue() == SeasonType.PRODUCT_FIXED_TYPE.getCode()) {
            Long fixedProductId = order.getProductId();
            FixedSeasonDetailsDTO fixedSeason = productService.getFixedProductBaseDTO(fixedProductId);
            if (Objects.isNull(fixedSeason)) {
                return Result.failed(SystemError.SEASON_TICKET_20004);
            } else {
                Integer backTerms = fixedSeason.getBackTerms();
                if (1 == backTerms) {
                    return Result.failed(SystemError.SEASON_TICKET_20023);
                }
            }
        }

        UpdateWrapper<SeasonOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(SeasonOrder::getId, req.getId());
        //修改付款状态为已取消
        updateWrapper.lambda().set(SeasonOrder::getPaymentStatus, OrderPaymentStatus.ALREADY_CANCEL.getCode());
        //修改预订状态为失败
        updateWrapper.lambda().set(SeasonOrder::getScheduledStatus, OrderScheduledStatus.RESERVE_FAIL.getCode());
        //改取消状态为成功
        updateWrapper.lambda().set(SeasonOrder::getCancelStatus, OrderCancelStatus.ALREADY_REFUND.getCode());
        seasonOrderMapper.update(null, updateWrapper);
        //创建一个退款记录  记录退款原因
        LocalDateTime now = LocalDateTime.now();
        SeasonOrderRefund seasonOrderRefund = new SeasonOrderRefund();
        seasonOrderRefund.setId(SnowflakeIdWorker.nextId());
        seasonOrderRefund.setOrderId(req.getId());
        seasonOrderRefund.setIsDeleted(IsDeletedCode.NO.getCode());
        seasonOrderRefund.setCreateId(currentUser.getId());
        //取消原因
        seasonOrderRefund.setRefundReason(req.getRefundReason());
        seasonOrderRefund.setGmtCreate(now);
        //备注
        if (StringUtils.isBlank(req.getRemark())) {
            seasonOrderRefund.setRemark("未付款取消订单");
        } else {
            seasonOrderRefund.setRemark(req.getRemark());
        }
        seasonOrderRefund.setStatus(OrderRefundStatus.REFUND_SUCCESSFUL.getCode());
        seasonOrderRefundMapper.insert(seasonOrderRefund);
        //(取消订单后)释放订单
        backStock(req.getId(), currentUser.getId());
        updateStatusToAppUser(order.getId());
        return Result.success(req.getId());
    }


    /* @MethodName: 取消订单/退款 需要走流程
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/30 10:08
     **/
    @Override
    public Result refundOrder(SeasonOrderRefundReq req, TokenUser currentUser) {
        SeasonOrder order = seasonOrderMapper.selectById(req.getOrderId());

        if (Objects.isNull(order)) {
            return Result.failed(SystemError.SEASON_TICKET_20021);
        }
        //套票业务类型枚举
        long businessTypeId = SystemBusinessType.FIXED_PACKAGE_TICKET.getCode();
        Boolean isFixed = order.getProductType() == SeasonType.PRODUCT_FIXED_TYPE.getCode() ? true : false;
        if (!isFixed) {
            businessTypeId = SystemBusinessType.DYNAMIC_PACKAGE_TICKET.getCode();
        }
        //如果是 固定套票 需要查出改套票的 退改条款
        if (isFixed) {
            Long fixedProductId = order.getProductId();
            FixedSeasonDetailsDTO fixedSeason = productService.getFixedProductBaseDTO(fixedProductId);
            if (Objects.isNull(fixedSeason)) {
                return Result.failed(SystemError.SEASON_TICKET_20004);
            } else {
                Integer backTerms = fixedSeason.getBackTerms();
                if (1 == backTerms) {
                    return Result.failed(SystemError.SEASON_TICKET_20023);
                }
            }
        }
        LocalDateTime now = LocalDateTime.now();
        List<SeasonOrderRefundDetailReq> seasonOrderRefundDetailReqList = req.getSeasonOrderRefundDetailReqList();
        List<SeasonOrderRefund> list = seasonOrderRefundDetailReqList.stream().map(
                refundReq -> {
                    SeasonOrderRefund refund = EntityUtil.copy(refundReq, SeasonOrderRefund.class);
                    refund.setId(SnowflakeIdWorker.nextId());
                    refund.setOrderId(req.getOrderId());
                    //退款单号
                    refund.setRefundNumber(SeasonOrderManager.getRefundNumber());
                    refund.setCreateId(currentUser.getId());
                    refund.setGmtCreate(now);
                    refund.setIsDeleted(IsDeletedCode.NO.getCode());
                    refund.setRemark(req.getRefundReason());
                    //退款时候汇率
                    refund.setRefundTimeRate(getCrmExchangeRateById(refundReq.getRefundCurrencyId()));
                    //审批中
                    refund.setStatus(OrderRefundStatus.AUDITING.getCode());
                    return refund;
                }
        ).collect(Collectors.toList());
        seasonOrderRefundMapper.insertBatchSomeColumn(list);

        UpdateWrapper<SeasonOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(SeasonOrder::getId, req.getOrderId());

        //订单改取消状态为审批中
        updateWrapper.lambda().set(SeasonOrder::getCancelStatus, OrderCancelStatus.UNDER_APPROVAL.getCode());
        updateWrapper.lambda().set(SeasonOrder::getGmtModified, currentUser.getId());
        updateWrapper.lambda().set(SeasonOrder::getGmtCreate, now);
        seasonOrderMapper.update(null, updateWrapper);
        //审批类型id 退款
        long approvalTypeId = SysApprovalType.CANCEL_FIXED.getCode();
        long businessId = req.getOrderId();
        long userId = currentUser.getId();
        //添加一个退款审批流程
        Result<ApprovalStartDTO> result = sysApprovalService.start(businessTypeId, approvalTypeId, businessId, userId, null, null);
        updateStatusToAppUser(order.getId());
        return Result.success(result);

    }

    /* @MethodName: 取消订单后释放库存
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/13 17:16
     **/
    private void backStock(Long orderId, Long userId) {
        SeasonOrder order = seasonOrderMapper.selectById(orderId);
        if (Objects.isNull(order)) {
            SeasonIndividualType productFlagEnum = SeasonIndividualType.getEnumType(order.getSeasonPackageProductFlag());//标识
            switch (productFlagEnum) {
                case AIR:
                    orderAirService.backStock(orderId, userId);
                    break;
                case HOTEL:
                    //  orderHotelService.playSupplierOrder(orderId, user);
                    break;
                case BUS:
                    // orderBusService.playSupplierOrder(orderId, user);
                    break;
                case SHIP:
                    // orderShipService.playSupplierOrder(orderId, user);
                    break;
                case TRAIN:
                    // orderTrainService.playSupplierOrder(orderId, user);
                    break;
                case SCENIC:
                    // orderScenicService.playSupplierOrder(orderId, user);
                case LOCALFUN:
                    //释放库存
                    orderLocalFunService.backStock(orderId, userId);
                    break;
            }
        }
    }

    /* @MethodName: 套票退款 审批
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/30 11:31
     **/
    @Override
    public Result refundAuditResult(RefundAuditReq req, TokenUser user) {
        Long approvalId = req.getApprovalId();
        Long userId = req.getUserId();
        Integer status = req.getStatus();
        String comments = req.getComments();
        SeasonOrder seasonOrder = getById(approvalId);
        if (Objects.isNull(seasonOrder)) {
            throw new BusinessException(SystemError.SEASON_TICKET_20021);
        }
        //校验审批状态是否正确
        ApprovalStatus approvalStatus = ApprovalStatus.getDefined(req.getStatus());
        if (Objects.isNull(approvalStatus)) {
            throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7012);
        }
        Result<ApprovalCheckDTO> result = sysApprovalService.check(approvalId, userId, status, comments);
        if (!Objects.isNull(result)) {
            if (!result.isSuccess()) {
                throw new BusinessException(SystemError.getDefined(result.getCode()));
            }
            //如果是审批通过并且审批流畅未结束则直接返回
            if (ApprovalStatus.REVIEW_YES.equals(approvalStatus) && !result.getData().getIsFinish()) {
                return Result.success();
            }
            //改变审核状态
            UpdateWrapper<SeasonOrderRefund> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().eq(SeasonOrderRefund::getOrderId, req.getBusinessId());
            updateWrapper.lambda().set(SeasonOrderRefund::getStatus, OrderCancelStatus.ALREADY_REFUND.getCode());
            updateWrapper.lambda().set(SeasonOrderRefund::getGmtModified, userId);
            updateWrapper.lambda().set(SeasonOrderRefund::getGmtCreate, LocalDateTime.now());
            updateWrapper.lambda().set(SeasonOrderRefund::getRejectReason, comments);
            seasonOrderRefundMapper.update(null, updateWrapper);
            //
            UpdateWrapper<SeasonOrder> orderUpdateWrapper = new UpdateWrapper<>();
            orderUpdateWrapper.lambda().eq(SeasonOrder::getId, req.getBusinessId());
            orderUpdateWrapper.lambda().set(SeasonOrder::getCancelStatus, OrderCancelStatus.APPROVAL_SUCCESS.getCode());
            orderUpdateWrapper.lambda().set(SeasonOrder::getGmtModified, userId);
            orderUpdateWrapper.lambda().set(SeasonOrder::getGmtCreate, LocalDateTime.now());
            seasonOrderMapper.update(null, orderUpdateWrapper);

            //审批通过 通知财务系统
            refundNotificationFinance(user, seasonOrder);
            updateStatusToAppUser(seasonOrder.getId());
        }
        return Result.success();
    }

    /* @MethodName: 审批通过 通知财务系统
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/23 15:44
     **/
    private void refundNotificationFinance(TokenUser user, SeasonOrder seasonOrder) {
        Long saleDeptId = iSysUserService.loadUserByParam(seasonOrder.getSalesmanId(), 1).getDeptId();
        Boolean isFixed = seasonOrder.getProductType() == 1 ? true : false;
        QueryWrapper<SeasonOrderCollection> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeasonOrderCollection::getIsDeleted, IsDeletedCode.NO.getCode());
        queryWrapper.lambda().eq(SeasonOrderCollection::getOrderId, seasonOrder.getId());
        List<SeasonOrderCollection> collectionList = seasonOrderCollectionMapper.selectList(queryWrapper);
        List<BillAddRefundReq> billAddRefundList = new LinkedList<>();
        if (CollectionUtils.isNotEmpty(collectionList)) {
            for (SeasonOrderCollection collection : collectionList) {
                BillAddRefundReq refundReq = new BillAddRefundReq();
                refundReq.setBillNumber(collection.getCollectionNumber());
                if (isFixed) {
                    refundReq.setBusinessType(SystemBusinessType.FIXED_PACKAGE_TICKET.getCode());
                } else {
                    refundReq.setBusinessType(SystemBusinessType.DYNAMIC_PACKAGE_TICKET.getCode());
                }
                refundReq.setCollectionAmount(collection.getCollectionAmount());
                refundReq.setCurrencyId(collection.getCurrencyId());
                refundReq.setCurrencyName(collection.getCurrency());
                refundReq.setExchangeRate(collection.getExchangeRate());
                refundReq.setSaleOrderId(collection.getOrderId());
                refundReq.setProductId(Arrays.asList(seasonOrder.getProductId()));
                refundReq.setProductName(seasonOrder.getProductName());
                refundReq.setProductNumber(String.valueOf(seasonOrder.getProductId()));
                refundReq.setResourceInfo(Arrays.asList(seasonOrder.getSeasonPackageProductFlag()));
                refundReq.setSaleUserId(seasonOrder.getSalesmanId());
                refundReq.setSaleUserName(seasonOrder.getSalesmanName());
                refundReq.setSaleDeptId(saleDeptId);
                refundReq.setRefundTypeId(collection.getCollectionWayId());
                refundReq.setRefundType(collection.getCollectionWay());
                AccountJson aj = new AccountJson();
                aj.setCardNumber(collection.getPayer());
                refundReq.setRefundAccountJson(aj);
                refundReq.setRefundTime(LocalDateTime.now());
                // refundReq.setPayVoucherJson(collection.getCollectionCertificateJson);
                refundReq.setRefundRemark(collection.getRemark());
                refundReq.setUserId(user.getId());
                billAddRefundList.add(refundReq);
            }
        }

        Result result = financeBillService.addRefund(billAddRefundList);
        if (!result.isSuccess()) {
            throw new BusinessException(SystemError.getDefined(result.getCode()));
        }
    }


    /* @MethodName: 银联优惠相关信息 以港币为准
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/25 19:22
     **/
    private BigDecimal getAmountByBankReference(SeasonOrder order, SeasonOrderCollection orderCollection, TokenUser user) {
        OperateBankConformQueryReq operateBankConformQueryReq = new OperateBankConformQueryReq();
        operateBankConformQueryReq.setId(orderCollection.getUnionpayDiscountId());//银联优惠id
        operateBankConformQueryReq.setCardNumber(orderCollection.getCollectionNumber());//卡号
        operateBankConformQueryReq.setTotalPaidIn(order.getOrderAmount());//订单金额
        operateBankConformQueryReq.setBusinessType(SystemBusinessType.FIXED_PACKAGE_TICKET.getCode());
        operateBankConformQueryReq.setRelationId(order.getId());
        operateBankConformQueryReq.setChannelId(OrderSource.CPM.getCode().longValue());//订单来源
        operateBankConformQueryReq.setUserId(user.getId());
        BigDecimal discountAmount = BigDecimal.ZERO;//银行支付的金额
        //获取银联优惠
        Result<OperateBankPreferenceQueryDTO> operateBankPreferenceQueryDTOResult = operateBankPreferenceService.queryConform(operateBankConformQueryReq);
        if (!operateBankPreferenceQueryDTOResult.isSuccess()) {
            // 校验银行优惠不满足条件
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60018);
        }
        OperateBankPreferenceQueryDTO bankQueryDto = operateBankPreferenceQueryDTOResult.getData();
        if (bankQueryDto.getDiscountType() == 1) {
            // 校验订单总额是否符合满减优惠
            if (order.getOrderAmount().compareTo(bankQueryDto.getFullAmount()) >= 0) {
                discountAmount = bankQueryDto.getReductionAmount();
            } else {
                // 校验银行优惠不满足条件
                throw new BusinessException(SystemError.AIREXPRESS_ORDER_60018);
            }
        } else {
            // 使用百分比优惠
            BigDecimal currentAmount = order.getReceivableAmount().multiply(new BigDecimal(String.valueOf(bankQueryDto.getDiscountPercent())));
            discountAmount = currentAmount.compareTo(bankQueryDto.getMaxDiscount()) > 0 ? bankQueryDto.getMaxDiscount() : currentAmount;
        }

        /**
         * 扣减银联优惠
         */
        OperateBankDeductReq deductReq = new OperateBankDeductReq();
        deductReq.setId(orderCollection.getUnionpayDiscountId());//银联优惠ID
        deductReq.setCardNumber(orderCollection.getPayer());//卡号
        deductReq.setTotalPaidIn(order.getOrderAmount());//订单金额
        deductReq.setBusinessType(SystemBusinessType.AIR_EXPRESS.getCode());
        deductReq.setRelationId(order.getId());//订单ID
        deductReq.setChannelId(OrderSource.CPM.getCode().longValue());//订单来源
        // deductReq.setUserId(user.getId());
        TokenUser tokenUser = new TokenUser();
        tokenUser.setId(user.getId());
        Result deductResult = operateBankPreferenceService.deduct(deductReq, tokenUser);
        if (!deductResult.isSuccess()) {
            // 校验银行优惠不满足条件
            SystemError defined = SystemError.getDefined(deductResult.getCode());
            throw new BusinessException(defined);
        }
        return discountAmount;
    }

    /* @MethodName: 根据币种id 获取汇率值
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/25 18:17
     **/
    public BigDecimal getCrmExchangeRateById(Long currencyId) {
        MainDataCurrencyUpdateStatusReq currencyReq = new MainDataCurrencyUpdateStatusReq();
        currencyReq.setId(currencyId); //币种
        //RPC 查询汇率
        Result<MainDataCurrencyQueryDTO> result = mainDataCurrencyService.query(currencyReq);
        int code = result.getCode();
        if (code != 0) {
            new BusinessException(SystemError.SEASON_TICKET_20011);
        }
        MainDataCurrencyQueryDTO currencyDto = result.getData();
        //获取门市汇率
        BigDecimal marketExchangeRate = currencyDto.getMarketExchangeRate();
        return marketExchangeRate;

    }

    /* @MethodName: 通知旅客
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/8 10:46
     **/
    @Override
    public Result notice(SeasonOrderNoticeReq seasonOrderNoticeReq) {
        return Result.success();
    }


    /* @MethodName: 动态套票 各个单项的 确认
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/14 10:45
     **/
    @Override
    public Result affirmDynamicOrder(DynamicAffirmOrderReq req) {
        // 1:机票 2:酒店 3:巴士 4:船票 5:火车票 6:景点门票 7:当地玩乐
        SeasonIndividualType productFlagEnum = SeasonIndividualType.getEnumType(req.getProductFlag());
        switch (productFlagEnum) {
            case AIR:
                orderAirService.changeAffirmState(req.getOrderId(), req.getScheduledStatus());
                break;
            case HOTEL:
                orderHotelService.changeAffirmState(req.getOrderId(), req.getScheduledStatus());
                break;

            case BUS:
                orderBusService.changeAffirmState(req.getOrderId(), req.getScheduledStatus());
                break;

            case SHIP:
                orderShipService.changeAffirmState(req.getOrderId(), req.getScheduledStatus());
                break;

            case TRAIN:
                orderTrainService.changeAffirmState(req.getOrderId(), req.getScheduledStatus());
                break;

            case SCENIC:
                orderScenicService.changeAffirmState(req.getOrderId(), req.getScheduledStatus());

            case LOCALFUN:
                orderLocalFunService.changeAffirmState(req.getOrderId(), req.getScheduledStatus());
                break;
        }

        return Result.success();
    }

    /* @MethodName: 动态套票 退款状态
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/20 10:12
     **/
    @Override
    public Result cancelOrderStatus(CancelStatusReq req) {
        // 1:机票 2:酒店 3:巴士 4:船票 5:火车票 6:景点门票 7:当地玩乐
        SeasonIndividualType productFlagEnum = SeasonIndividualType.getEnumType(req.getProductFlag());
        switch (productFlagEnum) {
            case AIR:
                orderAirService.changeCancelOrderState(req.getOrderId(), req.getCancelStatus());
                break;
            case HOTEL:
                orderHotelService.changeCancelOrderState(req.getOrderId(), req.getCancelStatus());
                break;

            case BUS:
                orderBusService.changeCancelOrderState(req.getOrderId(), req.getCancelStatus());
                break;

            case SHIP:
                orderShipService.changeCancelOrderState(req.getOrderId(), req.getCancelStatus());
                break;

            case TRAIN:
                orderTrainService.changeCancelOrderState(req.getOrderId(), req.getCancelStatus());
                break;

            case SCENIC:
                orderScenicService.changeCancelOrderState(req.getOrderId(), req.getCancelStatus());

            case LOCALFUN:
                orderLocalFunService.changeCancelOrderState(req.getOrderId(), req.getCancelStatus());
                break;
        }
        return Result.success();
    }

    @Override
    public Result<List<MySeasonOrderDTO>> recentToNow(LocalDateTime recent, LocalDateTime now) {
        List<SeasonOrder> orderList = baseMapper.selectList(Wrappers.<SeasonOrder>lambdaQuery()
                .eq(SeasonOrder::getIsDeleted, IsDeletedCode.NO.getCode())
                .ge(recent != null, SeasonOrder::getGmtModified, recent)
                .le(SeasonOrder::getGmtModified, now));
        return Result.success(EntityUtil.copyList(orderList, MySeasonOrderDTO.class));
    }

    /**
     * 构建订单ESDTO
     * @param orderId
     * @return
     */
    public MySeasonOrderDTO buildEsOrderDTO(Long orderId) {
        MySeasonOrderDTO orderDTO = EntityUtil.copy(baseMapper.selectById(orderId), MySeasonOrderDTO.class);
        return orderDTO;
    }

    /**
     * 异步发送订单数据到个人中心
     * @param orderId 订单Id
     */
    public void sendOrderToAppUser(Long orderId) {
        CompletableFuture.runAsync(() -> {
            try {
                MySeasonOrderDTO orderDTO = buildEsOrderDTO(orderId);
                orderEsService.saveOrderToEs(orderDTO, SystemBusinessType.FIXED_PACKAGE_TICKET);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 异步更新订单状态到个人中心
     */
    public void updateStatusToAppUser(Long orderId) {
        CompletableFuture.runAsync(() -> {
            try {
                SeasonOrder order = baseMapper.selectById(orderId);
                orderEsService.updateStatusToEs(order.getId(),SystemBusinessType.FIXED_PACKAGE_TICKET.getCode(),
                        null, order.getPaymentStatus(), order.getScheduledStatus(),
                        order.getCancelStatus());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}
